package com.ccteam.fluidmusic.ui.moment

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.setFragmentResultListener
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.ccteam.fluidmusic.NavAddMediaDirections
import com.ccteam.fluidmusic.R
import com.ccteam.fluidmusic.databinding.*
import com.ccteam.fluidmusic.utils.EventObserver
import com.ccteam.fluidmusic.utils.PictureSelectorGlideEngine
import com.ccteam.fluidmusic.view.adapters.ViewBindViewHolder
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.fluidmusic.ui.playlist.select.AddOnlineMediaFragment
import com.ccteam.fluidmusic.ui.playlist.select.AddOnlineMediaFragment.Companion.TYPE_ADD_MEDIA_MOMENTS
import com.ccteam.fluidmusic.ui.base.BasePhotoPickerViewModel
import com.ccteam.fluidmusic.widget.SNACKBAR_BOTTOM
import com.ccteam.fluidmusic.widget.snackbar
import com.ccteam.model.moment.MOMENT_SHARE_TYPE_ALBUM
import com.ccteam.model.moment.MOMENT_SHARE_TYPE_MUSIC
import com.ccteam.model.moment.MOMENT_SHARE_TYPE_PLAYLIST
import com.ccteam.shared.result.moment.MomentListItem
import com.luck.picture.lib.PictureSelector
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.listener.OnResultCallbackListener
import dagger.hilt.android.AndroidEntryPoint
import java.lang.ref.WeakReference
import javax.inject.Inject

/**
 *
 * @author Xiaoc
 * @since 2020/1/24
 *
 * 发布朋友圈界面
 *
 * */
@AndroidEntryPoint
class PublishMomentFragment : Fragment() {

    companion object{
        const val SHOULD_REFRESH_MOMENT = "refresh_moment"
    }

    private var _binding: FragmentPublishMomentBinding? = null
    private val binding get() = _binding!!

    private val basePhotoPickerViewModel: BasePhotoPickerViewModel by activityViewModels()

    private val publishMomentViewModel by activityViewModels<PublishMomentViewModel>()

    private lateinit var adapter: SelectPhotoAdapter

    @Inject lateinit var glideEngine: PictureSelectorGlideEngine

    private lateinit var resultCallback: ResultCallback

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setFragmentResultListener(AddOnlineMediaFragment.RESULT_MOMENTS_TYPE_KEY){ _, bundle ->
            val shareItem = bundle.getParcelable<MomentListItem.MomentShareItem>(
                AddOnlineMediaFragment.RESULT_MOMENTS_TYPE_KEY
            )
            if(shareItem != null){
                publishMomentViewModel.setShareItem(shareItem)
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentPublishMomentBinding.inflate(inflater,container,false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        updateMomentContent(publishMomentViewModel.momentContent)

        adapter = SelectPhotoAdapter(basePhotoPickerViewModel.selectImages,selectPhotoClickCallback)
        binding.rvSelectPhoto.adapter = adapter

        binding.toolbarAddMoment.setNavigationOnClickListener {
            requireActivity().finish()
        }

        resultCallback = ResultCallback(adapter,basePhotoPickerViewModel)

        publishMomentViewModel.shareItem.observe(viewLifecycleOwner, {
            updateShareItem(it)
        })

        publishMomentViewModel.enablePublishMomentButton.observe(viewLifecycleOwner, {
            binding.btnPublishMoment.isEnabled = it
        })

        publishMomentViewModel.loadMessage.observe(viewLifecycleOwner, EventObserver{
            updateStateUI(it is LoadMessage.Loading)
            if(it is LoadMessage.Error){
                view.snackbar(it.errorMessage.description.toString(), SNACKBAR_BOTTOM).show()
            } else if(it is LoadMessage.Success){
                view.snackbar(R.string.description_success_publish, SNACKBAR_BOTTOM).show()
                requireActivity().setResult(Activity.RESULT_OK, Intent().apply {
                    putExtra(SHOULD_REFRESH_MOMENT,true)
                })
                requireActivity().finish()
            }
        })

        binding.containerSelectShareContent.setOnClickListener {
            findNavController().navigate(NavAddMediaDirections.actionGlobalAddOnlineMediaFragment(
                TYPE_ADD_MEDIA_MOMENTS,null
            ))
        }

        binding.editMomentContent.addOnEditTextAttachedListener { inputLayout ->
            inputLayout.editText?.doOnTextChanged { text, _, _, _ ->
                publishMomentViewModel.setEnablePublishMoment(text.toString().isNotEmpty())
                publishMomentViewModel.setMomentContent(text.toString())
            }
        }

        binding.btnDeleteShareContent.setOnClickListener {
            publishMomentViewModel.clearShareItem()
        }

        binding.btnPublishMoment.setProgressButtonOnClickListener {
            publishMomentViewModel.publishMoment(basePhotoPickerViewModel.selectImages)
        }
    }

    private fun updateStateUI(isLoading: Boolean) = with(binding){
        containerSelectShareContent.isEnabled = !isLoading
        btnPublishMoment.setLoading(isLoading)
    }

    /**
     * 更新朋友圈输入的内容
     * 用于从其他Fragment返回后进行重新填充
     */
    private fun updateMomentContent(content: StringBuilder){
        binding.editMomentContent.editText?.setText(content.toString())
    }

    private fun updateShareItem(shareItem: MomentListItem.MomentShareItem?) = with(binding){
        btnDeleteShareContent.isVisible = shareItem != null
        ivShareFunction.isVisible = shareItem == null
        tvShareType.isVisible = shareItem != null

        Glide.with(ivShareImg)
            .load(shareItem?.imgUrl)
            .placeholder(R.drawable.ic_music)
            .into(ivShareImg)

        shareItem?.let {
            tvShareTitle.text = shareItem.title
            // 根据选择不同的分享内容显示不同内容
            when(shareItem.type){
                MOMENT_SHARE_TYPE_MUSIC ->{
                    tvShareType.text = getString(R.string.now_playing_tab_music)
                }
                MOMENT_SHARE_TYPE_PLAYLIST ->{
                    tvShareType.text = getString(R.string.online_music_playlistSheet_type)
                }
                MOMENT_SHARE_TYPE_ALBUM ->{
                    tvShareType.text = getString(R.string.online_music_album_type)
                }
            }
        } ?: run {
            tvShareTitle.text = getString(R.string.description_select_share_info)
        }
    }

    private val selectPhotoClickCallback = object: SelectPhotoClickCallback {

        override fun addButtonClicked() {
            PictureSelector.create(this@PublishMomentFragment)
                .openGallery(PictureMimeType.ofImage()) /* 打开图片浏览 */
                .imageEngine(glideEngine) /* 使用Glide引擎加载图片 */
                .maxSelectNum(basePhotoPickerViewModel.maxSelectCount) /* 最大选择数量 */
                .forResult(resultCallback) /* 回调接口 */
        }

        override fun itemClicked(view: View, position: Int,images: List<LocalMedia>) {
            if(images.isNotEmpty()){
                PictureSelector.create(this@PublishMomentFragment)
                    .externalPicturePreview(position,images,0) /* 点击图片预览 */
            }
        }

        override fun removeItem(position: Int) {
            basePhotoPickerViewModel.removeItem(position)
        }

    }

    /**
     * 选择图片的回调方法
     * 当使用 [PictureSelector] 选择完毕图片后回调此方法
     */
    private class ResultCallback(
        adapter: SelectPhotoAdapter,
        basePhotoPickerViewModel: BasePhotoPickerViewModel
    ): OnResultCallbackListener<LocalMedia>{
        private val mAdapterWeakReference = WeakReference(adapter)
        private val viewModel = WeakReference(basePhotoPickerViewModel)

        /**
         * 带着选择的图片数据返回
         * 我们将其加入到已选择图片列表并通知RecyclerView更新
         */
        override fun onResult(result: MutableList<LocalMedia>?) {
            mAdapterWeakReference.get()?.let {
                viewModel.get()?.addItem(result ?: mutableListOf())
                it.notifyDataSetChanged()
            }
        }

        override fun onCancel() {}

    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding.editMomentContent.clearOnEditTextAttachedListeners()

        _binding = null
    }

    class SelectPhotoAdapter(
        private val selectList: List<LocalMedia>,
        private val selectPhotoClickCallback: SelectPhotoClickCallback
    ): RecyclerView.Adapter<SelectPhotoAdapter.ImageViewHolder>(){

        var selectMax = 9

        companion object{
            private const val TYPE_ADD = 1
            private const val TYPE_PHOTO = 2
        }

        inner class ImageViewHolder(
            binding: GlobalSelectPhotoItemBinding
        ): ViewBindViewHolder<GlobalSelectPhotoItemBinding>(binding)

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
            return ImageViewHolder(GlobalSelectPhotoItemBinding.inflate(LayoutInflater.from(parent.context),parent,false))
        }

        override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
            // 如果是ADD图片，则点击后响应添加图片功能
            if(getItemViewType(position) == TYPE_ADD){
                holder.binding.ivSelectPhoto.setImageResource(R.drawable.miui_feedback_icon_add_screenshot_n)
                holder.binding.ivSelectPhoto.setOnClickListener {
                    selectPhotoClickCallback.addButtonClicked()
                }
                holder.binding.btnDeleteSelectPhoto.visibility = View.INVISIBLE
            } else {
                holder.binding.btnDeleteSelectPhoto.visibility = View.VISIBLE
                holder.binding.btnDeleteSelectPhoto.setOnClickListener {
                    val index = holder.absoluteAdapterPosition
                    delete(index)
                }
                holder.binding.ivSelectPhoto.setOnClickListener {
                    selectPhotoClickCallback.itemClicked(it,holder.absoluteAdapterPosition,selectList)
                }
                val item = selectList[position]

                Glide.with(holder.itemView)
                    .load(item.path)
                    .centerCrop()
                    .into(holder.binding.ivSelectPhoto)
            }

        }

        /**
         * 删除某一图片内容
         * 此处会调用回调接口通知ViewModel进行删除
         * 然后进行对应内容的更新通知
         */
        fun delete(position: Int){
            if(position != RecyclerView.NO_POSITION && selectList.size > position){
                selectPhotoClickCallback.removeItem(position)
                notifyItemRemoved(position)
                notifyItemRangeChanged(position,selectList.size)
            }
        }

        /**
         * 返回Item的数量，因为当图片小于9张时，会有一个ADD的图片占位
         * 需要+1
         */
        override fun getItemCount(): Int {
            return if(selectList.size < selectMax){
                selectList.size + 1
            } else {
                selectList.size
            }
        }

        /**
         * 返回Item的类型
         * 此处分ADD按钮和已选择图片类型
         */
        override fun getItemViewType(position: Int): Int {
            return if(isShowAddItem(position)){
                TYPE_ADD
            } else {
                TYPE_PHOTO
            }
        }

        private fun isShowAddItem(position: Int):Boolean = selectList.size == position


    }

    interface SelectPhotoClickCallback{
        /**
         * 添加按钮点击处理
         */
        fun addButtonClicked()

        /**
         * 图片点击后的处理，可以进行对应预览
         */
        fun itemClicked(view: View,position: Int,images: List<LocalMedia>)

        /**
         * 移除对应图片内容的处理
         */
        fun removeItem(position: Int)
    }
}